package client

import (
	"context"
	"github.com/go-kratos/kratos/v2/log"
	"github.com/go-kratos/kratos/v2/middleware/tracing"
	"github.com/go-kratos/kratos/v2/registry"
	"github.com/go-kratos/kratos/v2/selector"
	"github.com/go-kratos/kratos/v2/selector/filter"
	"github.com/go-kratos/kratos/v2/selector/wrr"
	kgrpc "github.com/go-kratos/kratos/v2/transport/grpc"
	"github.com/go-kratos/kratos/v2/transport/http"
	"google.golang.org/grpc"
	"math"
	"time"
)

// NewGrpcConnect  新建grpc连接
func NewGrpcConnect(endpoint string, d registry.Discovery, timeout time.Duration) *grpc.ClientConn {
	// 创建路由 Filter：筛选版本号为"1.0.0"的实例
	f := filter.Version("1.0.0")
	// 由于 gRPC 框架的限制，只能使用全局 balancer name 的方式来注入 selector
	selector.SetGlobalSelector(wrr.NewBuilder())
	endpoint = "discovery:///" + endpoint
	conn, err := kgrpc.DialInsecure(
		context.Background(),
		kgrpc.WithEndpoint(endpoint),
		kgrpc.WithDiscovery(d),
		kgrpc.WithTimeout(timeout),
		kgrpc.WithMiddleware(tracing.Client()),
		kgrpc.WithHealthCheck(true),
		kgrpc.WithPrintDiscoveryDebugLog(true),
		kgrpc.WithNodeFilter(f),
	)
	if err != nil {
		log.Errorw("kind", "grpc-client", "reason", "GRPC_CLIENT_CONNECTION_INIT_ERROR", "err", err)
	}
	return conn
}

func NewGrpcConnectByAddr(addr string, d registry.Discovery, timeout time.Duration) *grpc.ClientConn {
	conn, err := kgrpc.DialInsecure(
		context.Background(),
		kgrpc.WithEndpoint(addr),
		kgrpc.WithDiscovery(d),
		kgrpc.WithTimeout(timeout),
		kgrpc.WithMiddleware(tracing.Client()),
		kgrpc.WithHealthCheck(true),
		kgrpc.WithPrintDiscoveryDebugLog(true),
		kgrpc.WithOptions(grpc.WithInitialWindowSize(math.MaxInt32)),
		kgrpc.WithOptions(grpc.WithInitialConnWindowSize(math.MaxInt32)),
	)
	if err != nil {
		log.Errorw("kind", "grpc-client", "reason", "GRPC_CLIENT_CONNECTION_INIT_ERROR", "err", err)
	}
	return conn
}

func NewHttpConnect(endpoint string, d registry.Discovery, timeout time.Duration) *http.Client {
	// 创建路由 Filter：筛选版本号为"1.0.0"的实例
	f := filter.Version("1.0.0")
	// 创建 P2C 负载均衡算法 Selector，并将路由 Filter 注入
	selector.SetGlobalSelector(wrr.NewBuilder())
	endpoint = "discovery:///" + endpoint
	conn, err := http.NewClient(
		context.Background(),
		http.WithEndpoint(endpoint),
		http.WithDiscovery(d),
		http.WithTimeout(timeout),
		http.WithNodeFilter(f),
	)
	if err != nil {
		log.Errorw("kind", "http-client", "reason", "HTTP_CLIENT_CONNECTION_INIT_ERROR", "err", err)
	}
	return conn
}

func NewHttpConnectByAddr(addr string, d registry.Discovery, timeout time.Duration) *http.Client {
	conn, err := http.NewClient(
		context.Background(),
		http.WithEndpoint(addr),
		http.WithDiscovery(d),
		http.WithTimeout(timeout),
	)
	if err != nil {
		log.Errorw("kind", "http-client", "reason", "HTTP_CLIENT_CONNECTION_INIT_ERROR", "err", err)
	}
	return conn
}
